home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 4 / Example 4.2 / heightMap.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-07-11  |  6.3 KB  |  239 lines

  1. #include "heightMap.h"
  2. #include "debug.h"
  3.  
  4. const DWORD PARTICLE::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
  5. DWORD FtoDword(float f){return *((DWORD*)&f);}
  6.  
  7. float Noise(int x)
  8. {
  9.     x = (x<<13) ^ x;
  10.     return (1.0f - ((x * (x*x * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0f);    
  11. }
  12.  
  13. float CosInterpolate(float v1, float v2, float a)
  14. {
  15.     float angle = a * D3DX_PI;
  16.     float prc = (1.0f - cos(angle)) * 0.5f;
  17.     return  v1*(1.0f - prc) + v2*prc;
  18. }
  19.  
  20. HEIGHTMAP::HEIGHTMAP(IDirect3DDevice9* Dev, INTPOINT _size)
  21. {
  22.     try
  23.     {
  24.         m_pDevice = Dev;
  25.         m_size = _size;
  26.  
  27.         // Init sprite
  28.         D3DXCreateSprite(m_pDevice,&m_pSprite);
  29.  
  30.         //Reset the heightMap to 0
  31.         m_maxHeight = 15.0f;
  32.         m_pHeightMap = new float[m_size.x * m_size.y];
  33.         memset(m_pHeightMap, 0, sizeof(float) * m_size.x * m_size.y);
  34.  
  35.         //Set particle vertex buffer and texture to NULL
  36.         m_pVb = NULL;
  37.         m_pHeightMapTexture = NULL;
  38.     }
  39.     catch(...)
  40.     {
  41.         debug.Print("Error in HEIGHTMAP::HEIGHTMAP()");
  42.     }
  43. }
  44.  
  45. HEIGHTMAP::~HEIGHTMAP()
  46. {
  47.     Release();
  48. }
  49.  
  50. void HEIGHTMAP::Release()
  51. {
  52.     if(m_pHeightMap != NULL)delete [] m_pHeightMap;
  53.     if(m_pVb != NULL)m_pVb->Release();
  54.     if(m_pSprite != NULL)m_pSprite->Release();
  55.     if(m_pHeightMapTexture != NULL)m_pHeightMapTexture->Release();
  56. }
  57.  
  58. HRESULT HEIGHTMAP::LoadFromFile(char fileName[])
  59. {
  60.     try
  61.     {
  62.         //Reset the heightMap to 0
  63.         memset(m_pHeightMap, 0, sizeof(float) * m_size.x * m_size.y);
  64.  
  65.         //Initiate the texture variables
  66.         if(m_pHeightMapTexture != NULL)m_pHeightMapTexture->Release();
  67.         m_pHeightMapTexture = NULL;
  68.         D3DXIMAGE_INFO info;
  69.  
  70.         //Load the texture (and scale it to our heightMap m_size)
  71.         if(FAILED(D3DXCreateTextureFromFileEx(m_pDevice, fileName, m_size.x, m_size.y, 1, D3DUSAGE_DYNAMIC, 
  72.                                             D3DFMT_L8, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 
  73.                                             NULL, &info, NULL, &m_pHeightMapTexture)))return E_FAIL;
  74.  
  75.         //Lock the texture
  76.         D3DLOCKED_RECT sRect;
  77.         m_pHeightMapTexture->LockRect(0, &sRect, NULL, NULL);
  78.         BYTE *bytes = (BYTE*)sRect.pBits;
  79.  
  80.         //Extract height values from the texture
  81.         for(int y=0;y<m_size.y;y++)
  82.             for(int x=0;x<m_size.x;x++)
  83.                 {
  84.                     BYTE *b = bytes + y * sRect.Pitch + x;
  85.                     m_pHeightMap[x + y * m_size.x] = ((float)*b / 255.0f) * m_maxHeight;
  86.                 }
  87.                         
  88.         //Unlock the texture
  89.         m_pHeightMapTexture->UnlockRect(0);
  90.     }
  91.     catch(...)
  92.     {
  93.         debug.Print("Error in HEIGHTMAP::LoadFromFile()");
  94.     }
  95.  
  96.     return S_OK;
  97. }
  98.  
  99. HRESULT HEIGHTMAP::CreateRandomHeightMap(int seed, float noiseSize, float persistence, int octaves)
  100. {
  101.     if(m_pHeightMapTexture != NULL){m_pHeightMapTexture->Release(); m_pHeightMapTexture = NULL;}
  102.     m_pDevice->CreateTexture(m_size.x, m_size.y, 1, D3DUSAGE_DYNAMIC, D3DFMT_L8, D3DPOOL_DEFAULT, &m_pHeightMapTexture, NULL);
  103.  
  104.     D3DLOCKED_RECT lock;
  105.     m_pHeightMapTexture->LockRect(0, &lock, NULL, NULL);
  106.  
  107.     //For each map node
  108.     for(int y=0;y<m_size.y;y++)
  109.         for(int x=0;x<m_size.x;x++)
  110.         {
  111.             //Scale x & y to the range of 0.0 - m_size
  112.             float xf = ((float)x / (float)m_size.x) * noiseSize;
  113.             float yf = ((float)y / (float)m_size.y) * noiseSize;
  114.  
  115.             float total = 0;            
  116.  
  117.             // For each octave
  118.             for(int i=0;i<octaves;i++)
  119.             {
  120.                 //Calculate frequency and amplitude (different for each octave)
  121.                 float freq = pow(2, i);
  122.                 float amp = pow(persistence, i);
  123.  
  124.                 //Calculate the x,y noise coordinates
  125.                 float tx = xf * freq;
  126.                 float ty = yf * freq;
  127.                 int tx_int = tx;
  128.                 int ty_int = ty;
  129.  
  130.                 //Calculate the fractions of x & y
  131.                 float fracX = tx - tx_int;
  132.                 float fracY = ty - ty_int;
  133.  
  134.                 //Get the noise of this octave for each of these 4 points
  135.                 float v1 = Noise(tx_int + ty_int * 57 + seed);
  136.                 float v2 = Noise(tx_int+ 1 + ty_int * 57 + seed);
  137.                 float v3 = Noise(tx_int + (ty_int+1) * 57 + seed);
  138.                 float v4 = Noise(tx_int + 1 + (ty_int+1) * 57 + seed);
  139.  
  140.                 //Smooth in the X-axis
  141.                 float i1 = CosInterpolate(v1 , v2 , fracX);
  142.                 float i2 = CosInterpolate(v3 , v4 , fracX);
  143.  
  144.                 //Smooth in the Y-axis
  145.                 total += CosInterpolate(i1 , i2 , fracY) * amp;
  146.             }
  147.  
  148.             int b = 128 + total * 128.0f;
  149.             if(b < 0)b = 0;
  150.             if(b > 255)b = 255;
  151.  
  152.             BYTE *bDest = (BYTE*)lock.pBits;
  153.             bDest += y * lock.Pitch + x;
  154.             *bDest = b;
  155.  
  156.             //Save to heightMap
  157.             m_pHeightMap[x + y * m_size.x] = ((float)b / 255.0f) * m_maxHeight;
  158.         }
  159.  
  160.     m_pHeightMapTexture->UnlockRect(0);
  161.  
  162.     return S_OK;
  163. }
  164.  
  165. HRESULT HEIGHTMAP::CreateParticles()
  166. {
  167.     try
  168.     {
  169.         if(m_pVb != NULL)
  170.         {
  171.             m_pVb->Release();
  172.             m_pVb = NULL;
  173.         }
  174.  
  175.         if(FAILED(m_pDevice->CreateVertexBuffer(m_size.x * m_size.y * sizeof(PARTICLE), D3DUSAGE_DYNAMIC | D3DUSAGE_POINTS | D3DUSAGE_WRITEONLY, PARTICLE::FVF, D3DPOOL_DEFAULT, &m_pVb, 0)))
  176.             debug.Print("Failed to create particle vertex buffer");
  177.  
  178.         PARTICLE *v = NULL;
  179.         m_pVb->Lock(0, 0, (void**)&v, D3DLOCK_DISCARD);
  180.  
  181.         for(int y=0;y<m_size.y;y++)
  182.             for(int x=0;x<m_size.x;x++)
  183.             {
  184.                 float prc = m_pHeightMap[x + y * m_size.x] / m_maxHeight;
  185.                 int red =  255 * prc;
  186.                 int green = 255 * (1.0f - prc);
  187.  
  188.                 v->color = D3DCOLOR_ARGB(255, red, green, 0);
  189.                 v->position = D3DXVECTOR3(x, m_pHeightMap[x + y * m_size.x], -y);
  190.                 v++;
  191.             }
  192.         
  193.         m_pVb->Unlock();
  194.  
  195.     }
  196.     catch(...)
  197.     {
  198.         debug.Print("Error in HEIGHTMAP::CreateParticles()");
  199.         return E_FAIL;
  200.     }
  201.  
  202.     return S_OK;
  203. }
  204.  
  205. void HEIGHTMAP::Render()
  206. {
  207.     try
  208.     {
  209.         if(m_pVb != NULL)
  210.         {
  211.             m_pDevice->SetRenderState(D3DRS_LIGHTING, false);
  212.             m_pDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, true);
  213.             m_pDevice->SetRenderState(D3DRS_POINTSCALEENABLE, true);
  214.  
  215.             m_pDevice->SetRenderState(D3DRS_POINTSIZE, FtoDword(0.7f));
  216.             m_pDevice->SetRenderState(D3DRS_POINTSIZE_MIN, FtoDword(0.0f));
  217.             m_pDevice->SetRenderState(D3DRS_POINTSCALE_A, 0);
  218.             m_pDevice->SetRenderState(D3DRS_POINTSCALE_B, FtoDword(0.0f));
  219.             m_pDevice->SetRenderState(D3DRS_POINTSCALE_C, FtoDword(1.0f));
  220.             m_pDevice->SetRenderState(D3DRS_ZWRITEENABLE, false);
  221.  
  222.             m_pDevice->SetTexture(0, NULL);
  223.             m_pDevice->SetFVF(PARTICLE::FVF);
  224.             m_pDevice->SetStreamSource(0, m_pVb, 0, sizeof(PARTICLE));
  225.             m_pDevice->DrawPrimitive(D3DPT_POINTLIST, 0, m_size.x * m_size.y);
  226.         }
  227.  
  228.         if(m_pSprite != NULL)
  229.         {
  230.             m_pSprite->Begin(0);
  231.             m_pSprite->Draw(m_pHeightMapTexture, NULL, NULL, &D3DXVECTOR3(1.0f, 1.0f, 1.0f), 0xffffffff);
  232.             m_pSprite->End();    
  233.         }
  234.     }
  235.     catch(...)
  236.     {
  237.         debug.Print("Error in HEIGHTMAP::Render()");
  238.     }
  239. }